﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Text;
using System.Threading.Tasks;
using Abp.Application.Services.Dto;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Abp.Linq.Extensions;
using Camc.OutsourceProcession.Authorization.Users;
using Camc.OutsourceProcession.ManufacturingEquipment;
using Camc.OutsourceProcession.Order.Dto;
using Camc.OutsourceProcession.Organizations;
using Camc.OutsourceProcession.Printer;
using Camc.OutsourceProcession.ProduceTask.Dto;
using IdentityServer4.Validation;

namespace Camc.OutsourceProcession.Order
{
	public class ProductionOrderAppService:OutsourceProcessionAppServiceBase
	{
		private readonly IProductionOrderManager _productionOrderManager;
		private readonly IRepository<ProductionOrder,long> _productionOrderRepository;
		private readonly IRepository<ExecuteHistory, long> _executeHistoryRepository;
		private readonly IOrganizationUnitAppService _organizationUnitAppService;
		private readonly IPrintEquipmentAppService _printEquipmentAppService;
        private readonly IRepository<Equipment, long> _equipmentRepository;


		public ProductionOrderAppService(IProductionOrderManager productionOrderManager, IRepository<ProductionOrder, long> productionOrderRepository, IRepository<ExecuteHistory, long> executeHistoryRepository, IOrganizationUnitAppService organizationUnitAppService, IPrintEquipmentAppService printEquipmentAppService, IRepository<Equipment, long> equipmentRepository)
		{
			_productionOrderManager = productionOrderManager;
			_productionOrderRepository = productionOrderRepository;
			_executeHistoryRepository = executeHistoryRepository;
			_organizationUnitAppService = organizationUnitAppService;
			_printEquipmentAppService = printEquipmentAppService;
            _equipmentRepository = equipmentRepository;
        }

		/// <summary>
		/// 创建任务
		/// </summary>
		public long CreateOrder(CreateProductionOrderInput input)
		{
			var newOrderId = _productionOrderManager.CreateOrder(input.TaskCode, input.TaskKey, input.Quantity, input.DeliveryTime, _organizationUnitAppService.GetMyCompanyCode());
            PrintOrder(newOrderId);
            return newOrderId;

        }

		/// <summary>
		/// 暂停任务
		/// </summary>
		/// <param name="productionOrderId"></param>
		public void Suspend(long productionOrderId)
		{
			_productionOrderManager.Suspend(productionOrderId);
		}

		/// <summary>
		/// 任务恢复正常
		/// </summary>
		/// <param name="productionOrderId"></param>
		public void Normal(long productionOrderId)
		{
			_productionOrderManager.Normal(productionOrderId);
		}

		/// <summary>
		/// 取消任务
		/// </summary>
		/// <param name="productionOrderId"></param>
		public void Dispose(long productionOrderId)
		{
			_productionOrderManager.Dispose(productionOrderId);
		}

		/// <summary>
		/// 报废
		/// </summary>
		/// <param name="productionOrderId"></param>
		public void Scrap(long productionOrderId)
		{
			_productionOrderManager.Scrap(productionOrderId);
		}

		/// <summary>
		/// 从制造商处取回
		/// </summary>
		/// <param name="productionOrderId"></param>
		public void Renew(long productionOrderId)
		{
			_productionOrderManager.Renew(productionOrderId, _organizationUnitAppService.GetMyCompanyCode());
		}

		/// <summary>
		/// 制造商接收任务
		/// </summary>
		/// <param name="productionOrderId"></param>
		public void Receive(productionOrderInput input)
		{
			_productionOrderManager.Receive(input.ProductionOrderId, _organizationUnitAppService.GetMyCompanyCode());
		}

		/// <summary>
		/// 加工执行
		/// </summary>
		/// <param name="input"></param>
		public void Process(ProcessingOrderInput input)
        {
            var equipmentDisplayName = _equipmentRepository.Get(input.EquipmentId).DisplayName;
			_productionOrderManager.Process(input.ProductionOrderId, equipmentDisplayName);
		}

		/// <summary>
		/// 交付任务
		/// </summary>
		/// <param name="productionOrderId"></param>
		public void Deliver(productionOrderInput input)
		{
			_productionOrderManager.Deliver(input.ProductionOrderId);
		}

		/// <summary>
		/// 分解任务
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public List<long> Separate(SeparateOrderInput input)
		{
			var orderlist= _productionOrderManager.Separate(input.ProductionOrderId,input.SeparateCountList);

            foreach (var order in orderlist)
            {

                PrintOrder(order);

            }

            return orderlist;
        }


		/// <summary>
		/// 查询任务
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public PagedResultDto<ProductionOrderDto> GetProductionOrders(GetProductionOrderInput input)
		{
			var query = _productionOrderRepository.GetAll();

			query = query
				.WhereIf(!input.CompanyCode.IsNullOrWhiteSpace(), c => c.CompanyCode.Contains(input.CompanyCode) )
				.WhereIf(!input.ProductionProcessionStateIndex.IsNullOrWhiteSpace(), c => c.ProcessionState == (ProductionProcessionState)Enum.Parse(typeof(ProductionProcessionState), input.ProductionProcessionStateIndex))
					
				.WhereIf(!input.ProductionStateIndex.IsNullOrWhiteSpace(), c => c.State == (ProductionState)Enum.Parse(typeof(ProductionState), input.ProductionStateIndex))
				.WhereIf(!input.TaskCodeForOutside.IsNullOrWhiteSpace(),
					c => c.TaskCodeForOutside == input.TaskCodeForOutside)
				.WhereIf(input.DeliveryTime != null, c => c.DeliveryTime <= input.DeliveryTime);

			if (input.Sorting.IsNullOrWhiteSpace())
			{
				input.Sorting = "CreationTime desc";
			}

			var orderCount = query.Count();

			var orderList = query.OrderBy(input.Sorting).PageBy(input).ToList();

			var output = orderList.GroupJoin(_executeHistoryRepository.GetAll(),
				c => c.Id,
				d => d.ProductionOrderId,
				(order, histories) => new ProductionOrderDto
				{
					DeliveryTime = order.DeliveryTime,
					CurrentProcession = new ProcessionDto
					{
						Operation = histories.OrderByDescending(c=>c.CreationTime).FirstOrDefault().Operation,
						OperationTime = histories.OrderByDescending(c => c.CreationTime).FirstOrDefault().CreationTime,
						Operator = histories.OrderByDescending(c => c.CreationTime).FirstOrDefault().CreatorUserId.ToString(),
						ProcessLocation = histories.OrderByDescending(c => c.CreationTime).FirstOrDefault().ProcessLocation
					},
					Id = order.Id,
					CompanyCodeString = order.CompanyCode,
					ProcessionStateString = order.ProcessionState.ToString(),
					Quantity = order.Quantity,
					StateString = order.State.ToString(),
					TaskCodeForOutside = order.TaskCodeForOutside
				}).ToList();


			foreach (var orderDto in output)
			{
				orderDto.CurrentProcession.Operator = UserManager.Users
					.FirstOrDefault(c => c.Id == Convert.ToInt64(orderDto.CurrentProcession.Operator))?.UserName;
				orderDto.CompanyCodeString = _organizationUnitAppService.GetAllCompany().Result.FirstOrDefault(c => c.Code == orderDto.CompanyCodeString)?.DisplayName;
			}

			return new PagedResultDto<ProductionOrderDto>(
				orderCount,
				output
			);
		}

		/// <summary>
		/// 查询任务执行过程
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public List<ProcessionDto> GetProcessionOfProductionOrders(long orderId)
		{
			var historyList = _executeHistoryRepository.GetAll().Where(c => c.ProductionOrderId == orderId)
				.OrderByDescending(c => c.CreationTime).GroupJoin(
					UserManager.Users,
					d => d.CreatorUserId,
					c => c.Id,
					(histories, users) => new ProcessionDto
					{
						Operation = histories.Operation,
						OperationTime = histories.CreationTime,
						Operator = users.FirstOrDefault(c=>c.Id == histories.CreatorUserId).UserName,
						ProcessLocation = histories.ProcessLocation

					}).ToList();
			return historyList;
		}
		/// <summary>
		/// 获取所有任务状态
		/// </summary>
		/// <returns></returns>
		public List<ComboboxItemDto> GetComboboxItemForProductionState()
		{

			var allType = new List<ComboboxItemDto>();

			foreach (var value in Enum.GetValues(typeof(ProductionState)))
			{
				var type = new ComboboxItemDto(((int)(value)).ToString(), value.ToString());

				allType.Add(type);
			}

			return allType;
		}

		/// <summary>
		/// 获取所有任务执行状态
		/// </summary>
		/// <returns></returns>
		public List<ComboboxItemDto> GetComboboxItemForProductionProcessionState()
		{

			var allType = new List<ComboboxItemDto>();

			foreach (var value in Enum.GetValues(typeof(ProductionProcessionState)))
			{
				var type = new ComboboxItemDto(((int)(value)).ToString(), value.ToString());

				allType.Add(type);
			}

			return allType;
		}

		/// <summary>
		/// 打印条码
		/// </summary>
		/// <param name="orderId"></param>
		public void PrintOrder(long orderId)
		{
			var order = _productionOrderRepository.Get(orderId);

			PrintForOrder.Print(_printEquipmentAppService.GetMyPrinterSN(), GenerateQR(orderId), order.TaskCodeForOutside,
				order.Quantity.ToString(), order.DeliveryTime.ToShortDateString());

		}

		/// <summary>
		/// 生成条码
		/// </summary>
		/// <param name="orderId"></param>
		/// <returns>条码的编号是:外部任务号+内部加密任务key+数量+交付时间（用逗号隔开）</returns>
		public string GenerateQR(long orderId)
		{
			var order = _productionOrderRepository.Get(orderId);

			return String.Format($"{order.Id},{order.TaskCodeForOutside},{order.TaskKey},{order.Quantity.ToString()},{order.DeliveryTime.ToShortDateString()}");

		}
	}
}
